using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using FlatRedBall;

using Xzipit.Interfaces;
using Gesture = Xzipit.Utilities.TouchManager.Gesture;

namespace Xzipit.Utilities
{
    public static class ActionManager
    {
        private static bool mFirstTimeInitialized = true;
        public static bool IsPaused = false;

        private static List<IPullable> mPullableObjects;
        private static List<IDraggable> mDraggableObjects;
        private static List<ITappable> mTappableObjects;
        private static List<IPinchable> mPinchableObjects;

        private static IDraggable mLastDragged;

        public static void Initialize()
        {
            if (mFirstTimeInitialized)
            {
                mPullableObjects = new List<IPullable>();
                mDraggableObjects = new List<IDraggable>();
                mTappableObjects = new List<ITappable>();
                mPinchableObjects = new List<IPinchable>();

                mFirstTimeInitialized = false;
            }

            TouchManager.Initialize();
        }

        public static void AddTappableObject(ITappable t)
        {
            mTappableObjects.Add(t);
        }

        public static void AddDraggableObject(IDraggable d)
        {
            mDraggableObjects.Add(d);
        }

        public static void AddPullableObject(IPullable p)
        {
            mPullableObjects.Add(p);
        }

        public static void AddPinchableObject(IPinchable p)
        {
            mPinchableObjects.Add(p);
        }

        public static void RemoveTappableObject(ITappable t)
        {
            mTappableObjects.Remove(t);
        }

        public static void RemoveDraggableObject(IDraggable d)
        {
            mDraggableObjects.Remove(d);
        }

        public static void RemovePullableObject(IPullable p)
        {
            mPullableObjects.Remove(p);
        }

        public static void RemovePinchableObject(IPinchable p)
        {
            mPinchableObjects.Remove(p);
        }

        public static void Update()
        {
            if (!IsPaused)
            {
                TouchManager.Update();

                switch (TouchManager.CurrentGesture)
                {
                    case Gesture.Tap:
                        foreach (ITappable item in mTappableObjects)
                        {
                            if (item.TouchArea.IsPointInside(TouchManager.EndPosition.X, TouchManager.EndPosition.Y))
                            {
                                item.OnTap();
                                break;
                            }
                        }
                        break;
                    case Gesture.Pull:
                        if (mLastDragged != null)
                        {
                            try
                            {
                                IPullable p = (IPullable)mLastDragged;
                                p.OnPull(TouchManager.StartPostion, TouchManager.EndPosition);
                            }
                            catch
                            {
                                foreach (IPullable item in mPullableObjects)
                                {
                                    if (item.TouchArea.IsPointInside(TouchManager.StartPostion.X, TouchManager.StartPostion.Y))
                                    {
                                        item.OnPull(TouchManager.StartPostion, TouchManager.EndPosition);
                                        break;
                                    }
                                }
                            }
                            finally
                            {
                                mLastDragged = null;
                            }
                        }
                        else
                        {
                            foreach (IPullable item in mPullableObjects)
                            {
                                if (item.TouchArea.IsPointInside(TouchManager.StartPostion.X, TouchManager.StartPostion.Y))
                                {
                                    item.OnPull(TouchManager.StartPostion, TouchManager.EndPosition);
                                    break;
                                }
                            }
                        }
                        break;
                    case Gesture.Drag:
                        if (mLastDragged != null)
                        {
                            mLastDragged.OnDrag(TouchManager.CurrentPosition);
                        }
                        else
                        {
                            foreach (IDraggable item in mDraggableObjects)
                            {
                                if (item.TouchArea.IsPointInside(TouchManager.StartPostion.X, TouchManager.StartPostion.Y))
                                {
                                    item.OnDrag(TouchManager.CurrentPosition);
                                    mLastDragged = item;
                                    break;
                                }
                            }
                        }
                        break;
                    case Gesture.Pinch:
                        foreach (IPinchable item in mPinchableObjects)
                        {
                            if (item.TouchArea.IsPointInside(TouchManager.StartPostion.X, TouchManager.StartPostion.Y))
                            {
                                item.OnBeginPinch();
                                break;
                            }
                        }
                        break;
                    case Gesture.PinchCompleted:
                        foreach (IPinchable item in mPinchableObjects)
                        {
                            if (item.TouchArea.IsPointInside(TouchManager.EndPosition.X, TouchManager.EndPosition.Y))
                            {
                                item.OnEndPinch();
                                break;
                            }
                        }
                        break;
                    case Gesture.None:
                        break;
                }
            }
        }

        public static void CleanUp()
        {
            mPullableObjects.Clear();
            mDraggableObjects.Clear();
            mTappableObjects.Clear();
            mPinchableObjects.Clear();

            mLastDragged = null;
        }
    }
}
